/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "标注物体构建.h"

#include <节点数据声明.h>
#include <Context/当前默认操作数据.h>
#include <core/shader_line.h>
#include <面/面.h>






void on_数值标注_mesh绘制参数设置(S_Mesh* me, const S_GPU内存块* 物体参数[2], uint32 多维子元素) {
	S_ShaderConst_TextAttr& GPU参数 = *(S_ShaderConst_TextAttr*)(me->m_绘制内存属性);

	GPU参数.MatrixOffset = 物体参数[0]->m_Mem.m_偏移;
	GPU参数.ColorPropOffset = 物体参数[1]->m_Mem.m_偏移;
	//uint32 num = me->m_光追材质链接.size();
	GPU参数.m_Address_MeshPropOffset = f_buf_getAddress2(me->m_网格元素变换属性);

	GPU参数.m_Address_TextCoord = f_buf_getAddress2(me->m_自定义参数[0]);
	GPU参数.m_Address_TextID = f_buf_getAddress2(me->m_自定义参数[1]);
	GPU参数.m_Address_TextID_Range = f_buf_getAddress2(me->m_自定义参数[2]);

	//me->m_GPU参数布局.m_纹理槽[0] = S_节点数据::g_字体_小.m_Tex;
	//me->m_GPU参数布局.m_纹理槽[1] = S_Engine::g_默认图标->m_Tex;

	GPU参数.fontSize = S_节点数据::g_字体_小.m_字号;
}

void on_数值标注线_mesh绘制参数设置(S_Mesh* me, const S_GPU内存块* 物体参数[2], uint32 多维子元素) {
	S_ShaderConst_TextAttr& GPU参数 = *(S_ShaderConst_TextAttr*)(me->m_绘制内存属性);

	GPU参数.MatrixOffset = 物体参数[0]->m_Mem.m_偏移;
	GPU参数.ColorPropOffset = 物体参数[1]->m_Mem.m_偏移;
	
	GPU参数.m_Address_MeshPropOffset = f_buf_getAddress2(me->m_网格元素变换属性);
	GPU参数.m_Address_TextCoord = f_buf_getAddress2(me->m_自定义参数[0]);
	GPU参数.m_Address_TextID = f_buf_getAddress2(me->m_自定义参数[1]);
	GPU参数.m_Address_TextID_Range = f_buf_getAddress2(me->m_自定义参数[2]);

	GPU参数.fontSize = S_节点数据::g_字体_小.m_字号;
}

S_物体* f_node_创建标注虚拟体(S_设备环境& ctx) {
	S_物体* ob = f_ob_创建(ctx, E_物体类型::t_标注);
	ob->m_视口显示模式 = E_物体视口显示::e_OVS_轮廓 | E_物体视口显示::e_OVS_面;
	ob->m_视口显示模式 |= ob->m_视口显示模式<<16;
	f_ob_set数据槽数量(ob, 2);

	S_Mesh* me = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_Vulkan);
	f_mesh_gen绘制内存属性_文本(me, {});
	f_mesh_gen网格元素绘制属性(me, 1);

	S_Mesh* line = f_surface_创建网格对象(0, ctx, E_网格数据枚举::e_Mesh_Vulkan);
	f_mesh_gen绘制内存属性_文本(line, {});
	f_mesh_gen网格元素绘制属性(line, 1);


	me->m_自定义参数.push_back(S_节点数据::g_小字体纹理UV);
	me->m_自定义参数.push_back(f_bm_alloc(f_buf_getGlobal().g_UI32动态属性_点, 0));
	me->m_自定义参数.push_back(f_bm_alloc(f_buf_getGlobal().g_GPU内存_点_uvec2, 0));
	me->mf_绘制参数设置 = on_数值标注_mesh绘制参数设置;

	line->m_自定义参数.push_back(S_节点数据::g_小字体纹理UV);
	line->m_自定义参数.push_back(f_bm_alloc(f_buf_getGlobal().g_UI32动态属性_点, 0));
	line->m_自定义参数.push_back(f_bm_alloc(f_buf_getGlobal().g_GPU内存_点_uvec2, 0));
	line->mf_绘制参数设置 = on_数值标注线_mesh绘制参数设置;
	

	(*(S_ShaderConst_TextAttr*)(me->m_绘制内存属性)).m_L_BackgroundText = (*S_全局缓存::g_默认图标)["左圆角矩形"];
	(*(S_ShaderConst_TextAttr*)(me->m_绘制内存属性)).m_R_BackgroundText = (*S_全局缓存::g_默认图标)["右圆角矩形"];

	f_ob_set数据(ob, me);
	f_ob_set数据(ob, line, 1);
	f_ob_set材质(ob, f_NodeCtx_get数值标注材质(), 0);
	f_ob_set材质(ob, f_NodeCtx_get数值标注线材质(), 1);

	return ob;
}

void f_node_销毁标注虚拟体(S_物体* ob) {
	f_surface_销毁网格(f_ob_getMesh(ob));
	f_ob_销毁(ob);
}




static void f_node_标注_坐标构建(S_Mesh* me, S_Mesh* line, std::vector<S_VC>& 坐标和颜色, uint32 num, vec2& 坐标偏移) {
	uint32 已有顶点参数数量 = 坐标和颜色.size();

	坐标和颜色.resize(num);
	if (已有顶点参数数量 < num) {
		for (uint32 i = 已有顶点参数数量; i < num; ++i) {
			坐标和颜色[i] = 坐标和颜色[0];
		}
	}
	f_mesh_fill顶点数据(me, 坐标和颜色);
	f_mesh_fill顶点数据(line, 坐标和颜色);

	(*(S_ShaderConst_TextAttr*)(me->m_绘制内存属性)).m_CoordOffset = 坐标偏移;
	(*(S_ShaderConst_TextAttr*)(line->m_绘制内存属性)).m_CoordOffset = 坐标偏移;
}

static void f_node_标注_坐标构建(S_Mesh* me, S_Mesh* line, std::vector<uint32>& 文字uvID, std::vector<uvec2>& 文字ID区间) {
	f_gbuf_fill(me->m_自定义参数[1], 文字uvID.data(), 0, 文字uvID.size());
	f_gbuf_fill(me->m_自定义参数[2], 文字ID区间.data(), 0, 文字ID区间.size());

	f_gbuf_fill(line->m_自定义参数[1], 文字uvID.data(), 0, 文字uvID.size());
	f_gbuf_fill(line->m_自定义参数[2], 文字ID区间.data(), 0, 文字ID区间.size());
}


static uint32 f_node_标注_数值构建(const std::u16string& 前缀, float32 value, std::vector<uint32>& 文字uvID) {
	auto t = 前缀 + f_浮点数值转宽字符串(value, 4);
	uint32 区间大小 = t.size();
	for (uint32 k = 0; k < 区间大小; ++k) 文字uvID.push_back(t[k]);
	return 区间大小;
}

static uint32 f_node_标注_数值构建(const std::u16string& 前缀, int32 value, std::vector<uint32>& 文字uvID) {
	auto t = 前缀 + f_整数值转宽字符串(value, 4);
	uint32 区间大小 = t.size();
	for (uint32 k = 0; k < 区间大小; ++k) 文字uvID.push_back(t[k]);
	return 区间大小;
}



void f_node_标注_设置标注网格(S_物体* ob, const int32& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, 1, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	uint32 区间大小 = f_node_标注_数值构建(前缀 + u":", data, 文字uvID);
	文字ID区间.push_back({ offset, 区间大小 });

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const float32& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, 1, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	uint32 区间大小 = f_node_标注_数值构建(前缀 + u":", data, 文字uvID);
	文字ID区间.push_back({ offset, 区间大小 });

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const vec3& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, 1, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	uint32 区间大小 = f_node_标注_数值构建(前缀 + u"/ x:", data.x, 文字uvID);
	区间大小 += f_node_标注_数值构建(u" y:", data.y, 文字uvID);
	区间大小 += f_node_标注_数值构建(u" z:", data.z, 文字uvID);
	文字ID区间.push_back({ offset, 区间大小 });
	
	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const S_I32Array& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;
	
	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);
	

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		auto t = 前缀 + u":" + f_整数值转宽字符串(data.ptr_userData[i]);
		uint32 区间大小 = t.size();
		for (uint32 k = 0; k < 区间大小; ++k) 文字uvID.push_back(t[k]);

		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const S_F32Array& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32 区间大小 = 区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i], 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}


void f_node_标注_设置标注网格(S_物体* ob, const S_Vec2Array& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32 
		区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i].x, 文字uvID);
		区间大小 += f_node_标注_数值构建(u"  y:", data.ptr_userData[i].y, 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const S_Vec3Array& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32
		区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i].x, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" y:", data.ptr_userData[i].y, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" z:", data.ptr_userData[i].z, 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const S_Vec4Array& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32
		区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i].x, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" y:", data.ptr_userData[i].y, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" z:", data.ptr_userData[i].z, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" w:", data.ptr_userData[i].w, 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}


void f_node_标注_设置标注网格(S_物体* ob, const S_iVec2Array& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32
			区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i].x, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" y:", data.ptr_userData[i].y, 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const S_iVec3Array&& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32
			区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i].x, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" y:", data.ptr_userData[i].y, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" z:", data.ptr_userData[i].z, 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}

void f_node_标注_设置标注网格(S_物体* ob, const S_iVec4Array&& data, std::vector<S_VC>& 坐标和颜色, std::u16string 前缀, vec2 坐标偏移) {
	uint32 num = data.count;

	S_Mesh* me = f_ob_getMesh(ob, 0);
	S_Mesh* line = f_ob_getMesh(ob, 1);
	f_node_标注_坐标构建(me, line, 坐标和颜色, num, 坐标偏移);

	std::vector<uint32> 文字uvID;
	std::vector<uvec2> 文字ID区间;

	uint32 offset = 0;
	for (uint32 i = 0; i < num; ++i) {
		uint32
			区间大小 = f_node_标注_数值构建(前缀 + u"x:", data.ptr_userData[i].x, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" y:", data.ptr_userData[i].y, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" z:", data.ptr_userData[i].z, 文字uvID);
		区间大小 += f_node_标注_数值构建(u" w:", data.ptr_userData[i].w, 文字uvID);
		文字ID区间.push_back({ offset, 区间大小 });
		offset += 区间大小;
	}

	f_node_标注_坐标构建(me, line, 文字uvID, 文字ID区间);
}




